package com.youlai.boot.core.tenant.config;

import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.youlai.boot.common.constant.TenantConstants;
import com.youlai.boot.core.tenant.annotation.IgnoreTenant;
import com.youlai.boot.core.tenant.context.TenantContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 动态数据源切面
 * 根据租户上下文自动切换数据源
 *
 * 【参考原项目的租户切换逻辑】
 */
@Slf4j
@Aspect
@Order(1) // 优先级要高于事务
@Component
public class DynamicDataSourceAspect {

    /**
     * 拦截所有 Mapper 方法，自动切换数据源
     */
    @Around("execution(* com.youlai.boot..mapper..*(..))")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Class<?> targetClass = point.getTarget().getClass();

        // 检查类上是否有 @IgnoreTenant 注解
        boolean hasIgnoreTenant = targetClass.isAnnotationPresent(IgnoreTenant.class);

        // 检查方法上是否有 @IgnoreTenant 注解
        if (!hasIgnoreTenant) {
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
            hasIgnoreTenant = method.isAnnotationPresent(IgnoreTenant.class);
        }

        String dataSourceKey;

        if (hasIgnoreTenant) {
            // 使用主数据源
            dataSourceKey = TenantConstants.MASTER_DATASOURCE;
            log.debug("使用主数据源: {}", dataSourceKey);
        } else {
            // 获取当前租户ID
            Long tenantId = TenantContextHolder.getTenantId();

            if (tenantId != null) {
                // 切换到租户数据源
                dataSourceKey = String.valueOf(tenantId);
                log.debug("切换到租户数据源: tenantId={}", tenantId);
            } else {
                // 没有租户上下文，使用主数据源
                dataSourceKey = TenantConstants.MASTER_DATASOURCE;
                log.warn("未找到租户上下文，使用主数据源");
            }
        }

        DynamicDataSourceContextHolder.push(dataSourceKey);

        try {
            return point.proceed();
        } finally {
            DynamicDataSourceContextHolder.poll();
        }
    }
}
